﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConceptsFramework.AbstractConceptElements;
using ConceptsFramework.Containers.Global;

namespace ConceptsFramework.Strategies.Clusters
{
    public abstract class AbstractOneLevelClusterStrategy
    {
        /// <summary>
        /// Unique clustering strategy name.
        /// </summary>
        public abstract string OneLevelClusterStrategyName
        {
            get;
        }

        /// <summary>
        /// Defines if a relationship belongs to a group
        /// </summary>
        /// <param name="analyzedRelationship">The analyzed relationship</param>
        /// <param name="aRelationshipGroup">The relationship group</param>
        /// <returns></returns>
        protected abstract bool AddToCurrentGroup(AbstractRelationship analyzedRelationship,
                                                  RelationshipsGroup aRelationshipGroup);

        /// <summary>
        /// Once the clusters have been computer, the metadata for each group will be defined 
        /// </summary>
        /// <param name="aRelationshipGroup"></param>
        /// <returns></returns>
        protected abstract string GetRelationshipGroupMetadata(RelationshipsGroup aRelationshipGroup);
        

        public RelationshipsGroup CreateClusters(RelationshipsGroup originalGroup)
        {
            RelationshipsGroup clusteredRelationshipGroup = new RelationshipsGroup();
            foreach(var aRelationshipKeyValue in originalGroup.RelationshipFlatContainer)
            {
                var aRelationship = aRelationshipKeyValue.Value;
                if (clusteredRelationshipGroup.Clusters.Count==0)
                {
                    RelationshipsGroup firstClusterRelationshipGroup = new RelationshipsGroup();
                    firstClusterRelationshipGroup.Add(aRelationship);
                    clusteredRelationshipGroup.Clusters.Add(firstClusterRelationshipGroup);
                }
                else
                {
                    bool hasRelationshipBeenAddedToGroup = false;
                    foreach(RelationshipsGroup aRelationshipGroup in clusteredRelationshipGroup.Clusters)
                    {
                        if (AddToCurrentGroup(aRelationship, aRelationshipGroup))
                        {
                            aRelationshipGroup.Add(aRelationship);
                            hasRelationshipBeenAddedToGroup = true;
                        }
                    }
                    if (!hasRelationshipBeenAddedToGroup)
                    {
                        RelationshipsGroup newClusterRelationshipGroup = new RelationshipsGroup();
                        newClusterRelationshipGroup.Add(aRelationship);
                        clusteredRelationshipGroup.Clusters.Add(newClusterRelationshipGroup);
                    }
                }
            }
            return clusteredRelationshipGroup;
        }
    }
}
